///<reference path="./index.d.ts"/>

export default class Time implements cddTime {
  duration: number = 1000
  afterPeriod: undefined | Function = undefined
  dateSeparator = '-'
  timeSeparator = ':'
  finally: undefined | Function = undefined
  times = 60
  stamp = 0
  isFirstPeriod = false

  private _date: Date
  private _id: any = 0
  private _isRunning = false

  constructor (params: CddTimeParams = {}) {
    Object.assign(this, params)
    this._date = params.date || new Date()
    this.init()
  }
  init (): void {
    this._isRunning = false
    this.stamp = this._date.getTime()
  }
  static readonly weekMap = [ '日', '一', '二', '三', '四', '五', '六' ]

  // date相关
  get year (): number {return this._date.getFullYear()}
  get month (): number {return this._date.getMonth() + 1}
  get day (): number {return this._date.getDate()}
  get dateStr (): string {
    return this.year + this.dateSeparator + Time.padStart(this.month) + this.dateSeparator + Time.padStart(this.day)
  }
  get DateStrZh () {
    return this.year + '年' + Time.padStart(this.month) + '月' + Time.padStart(this.day) + '日'
  }
  // get date (): string {return this.dateStr}

  // 时间相关
  get hours (): number {return this._date.getHours()}
  get minutes (): number {return this._date.getMinutes()}
  get seconds (): number {return this._date.getSeconds()}
  get timeSign (): string {
    return this.hours <= 12 ? 'AM' : 'PM'
  }
  get timeStr (): string {
    return Time.padStart(this.hours) + this.timeSeparator + Time.padStart(this.minutes) + this.timeSeparator + Time.padStart(this.seconds)
  }
  get timeStrZh (): string {
    return Time.padStart(this.hours) + '时' + Time.padStart(this.minutes) + '分' + Time.padStart(this.seconds) + '秒'
  }
  get time (): string {return this.timeStr}
  // 获取星期
  week (type = 'cn'): number | string {
    if (type === 'cn') {return Time.weekMap[ this._date.getDay() ]}
    return this._date.getDay()
  }

  // padStart
  static padStart (value: number | string, length = 2, str = '0'): string {
    value = '' + value
    if (value.length > length) return value

    if (String.prototype[ 'padStart' ]) {
      return (value).padStart(length, str)
    }
    let arr = []
    arr.length = length - value.length
    for (let i = arr.length; i > 0; i--) {
      arr[ i - 1 ] = str
    }
    return arr.join('') + value
  }

  start (): void {
    this._isRunning = true
    this.interval()
  }
  stop (): void {
    this._isRunning = false
    clearTimeout(this._id)
    console.log(`time is up`)
  }
  countDownStart (): void {
    let self = this
    let cb = this.afterPeriod
    this.afterPeriod = function () {
      if (this.times >= 0) {
        self.times -= 1
        cb && (cb(self))
      }
      if (this.times < 0) this.stop()
    }
    this.start()
  }

  private interval (): void {
    let self = this
    if (this.isFirstPeriod && this.afterPeriod) {
      this.isFirstPeriod = false
      this.afterPeriod(self)
    }
    if (self._isRunning) {
      this._id = setTimeout(() => {
        self._date = new Date()
        self.afterPeriod && (<Function>self.afterPeriod(self))
        self.interval()
      }, self.duration)
    } else {
      self.finally && (<Function>self.finally(self))
      return clearTimeout(self._id)
    }
  }
  /** 默认同String*/
  toString () {
    return `${this.dateStr} ${this.timeStr}`
  }
  /**中文字符串 */
  toStringZh () {
    return `${this.DateStrZh + this.timeStrZh}`
  }
}

